package net.j4love.thread;

import org.junit.Test;

import java.util.Random;
import java.util.concurrent.CountDownLatch;

/**
 * @author he peng
 * @create 2018/7/10 14:25
 * @see
 */
public class ThreadTest {

    @Test
    public void interruptTest0() throws Exception {

        Thread t = new Thread(new Runnable() {
            @Override
            public void run() {
                // 会清除中断状态 , 将中断状态设置为 true
                System.out.println("current thread interrupt before = " + Thread.interrupted());
                while (true) {
                    System.out.println("run ... ");
                }
            }
        });

        System.out.println("start before is interrupted = " + t.isInterrupted());
        t.start();
        System.out.println("start after is interrupted = " + t.isInterrupted());

        Thread.sleep(10);
        t.interrupt();
        System.out.println("interrupt after is interrupted = " + t.isInterrupted());

        // 线程在什么时候可以响应中断，在什么时候无法响应中断？
    }

    @Test
    public void interruptTest1() throws Exception {

        Thread t = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("current thread interrupt before = " + Thread.interrupted());
                while (true) {
                    System.out.println("run ... ");
                    try {
                        Thread.sleep(3000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        });

        t.start();
        Thread.sleep(300);

        t.interrupt();
    }

    @Test
    public void interruptTest2() throws Exception {

        final Object lock1 = new Object();
        final Object lock2 = new Object();

        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                while (true) {
                    synchronized (lock1) {
                        System.out.println("T1 hold lock1");
                        try {
                            Thread.sleep(300);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        synchronized (lock2) {
                            System.out.println("T1 hold lock2");
                        }
                    }
                }

            }
        });

        Thread t2 = new Thread(new Runnable() {
            @Override
            public void run() {
                while (true) {
                    synchronized (lock2) {
                        System.out.println("T2 hold lock2");
                        synchronized (lock1) {
                            System.out.println("T2 hold lock1");
                        }
                    }
                }
            }
        });

        t1.start();
        t2.start();

        Thread.sleep(5000);

        // 线程死锁状态下无法响应中断
        t1.interrupt();

        // 线程中断标记位设置生效了，但是线程却无法响应中断
        System.out.println("T1 is Interrupted " + t1.isInterrupted());
        System.out.println("T1 is Alive " + t1.isAlive());

        t2.interrupt();
        System.out.println("T2 is Interrupted " + t2.isInterrupted());
        System.out.println("T2 is Alive " + t2.isAlive());

        CountDownLatch downLatch = new CountDownLatch(1);
        downLatch.await();
    }


    @Test
    public void uncaughtExceptionHandlerTest() throws Exception {

        final Random random = new Random();
        Thread t = new Thread(new Runnable() {
            @Override
            public void run() {
                while (true) {

                    // 6 / 0 这样的异常没法被 Thread.UncaughtExceptionHandler 处理
//                    System.out.println("result = " + (6 / random.nextInt(3)));
                    if (random.nextInt(3) == 0) {
                        throw new RuntimeException("random number equals 3");
                    }
                }
            }
        });



        t.start();

        // 在线程启动前，启动后设置都可以
        t.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
            @Override
            public void uncaughtException(Thread t, Throwable e) {
                System.out.println("ThreadID : " + t.getId() + " UncaughtExceptionHandler run ... error : " + e.getMessage());
            }
        });

        Thread.sleep(3000);
    }


    @Test
    public void joinTest0() throws Exception {
        final Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(3000);
                    System.out.println("T1 sleep 3s");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });

        Thread t2 = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    // 等到 t1 线程执行结束之后 , t2 线程才开始执行 , join 函数阻塞
                    t1.join();
                    System.out.println("T2 run ... ");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });

        t2.start();
        t1.start();

        Thread.sleep(8000);

    }

    @Test
    public void yieldTest() throws Exception {

        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {

                // yield 当前线程原意放弃 CPU 使用权
                Thread.yield();
                while (true) {
                    System.out.println("T1 run ...");
                }
            }
        });

        Thread t2 = new Thread(new Runnable() {
            @Override
            public void run() {
                while (true) {
                    System.out.println("T2 run ...");
                }
            }
        });

        t1.start();
        Thread.sleep(20);
        t2.start();

        CountDownLatch downLatch = new CountDownLatch(1);
        downLatch.await();
    }

}
